package top.buluoluo.userservice.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import top.buluoluo.commoncore.constant.ResponseCode;
import top.buluoluo.commoncore.domain.response.Result;
import top.buluoluo.commoncore.utils.JwtUtil;
import top.buluoluo.userservice.dto.request.RegisterRequest;
import top.buluoluo.userservice.dto.request.UserAddressPageRequst;
import top.buluoluo.userservice.dto.response.UserDTO;
import top.buluoluo.userservice.dto.result.PageResult;
import top.buluoluo.userservice.entity.User;
import top.buluoluo.userservice.entity.UserAddress;
import top.buluoluo.userservice.mapper.UserAddressMapper;
import top.buluoluo.userservice.mapper.UserMapper;
import top.buluoluo.userservice.service.TokenManagerService;
import top.buluoluo.userservice.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private JwtUtil jwtUtil;
    @Autowired
    private PasswordEncoder passwordEncoder; // 注入spring security的密码编码器
    @Autowired
    private TokenManagerService tokenManagerService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserAddressMapper userAddressMapper;

    //    登录方法
    @Override
    public Result<Map<String, Object>> login(String username, String password) {
        // 1. 参数校验
        if (username == null || username.trim().isEmpty()) {
            return Result.failed(ResponseCode.VALIDATE_FAILED.getCode(), "用户名不能为空");
        }
        if (password == null || password.trim().isEmpty()) {
            return Result.failed(ResponseCode.VALIDATE_FAILED.getCode(), "密码不能为空");
        }
        // 2. 使用 LambdaQueryWrapper 构建查询条件
        // 类型安全，编译期就能发现错误，避免硬编码字段名（QueryWrapper）
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        //执行查询
        User user = this.getOne(queryWrapper);
        // 3. 登录逻辑判断
        if (user == null) {
            // 如果用户不存在返回错误代码401
            return Result.failed(ResponseCode.UNAUTHORIZED.getCode(), "用户不存在或密码错误"); // 模糊提示，安全考虑
        }
        // 4.使用PasswordEncoder进行安全校验
        if (!passwordEncoder.matches(password, user.getPasswordHash())) {
            return Result.failed(ResponseCode.UNAUTHORIZED.getCode(), "用户不存在或密码错误");
        }

        // 5. 例如用户是否被禁用
        if (user.getStatus() != 1) { // 假设 1 为正常状态
            return Result.failed(ResponseCode.FORBIDDEN.getCode(), "用户已被禁用，请联系管理员");
        }

        UserDTO userDTO = UserDTO.fromEntity(user); // 使用工厂方法
        String token = jwtUtil.generateToken(userDTO.getId(), getUserRoles(user.getId()));//生成 Token
        tokenManagerService.storeToken(token, user.getId(), jwtUtil.getExpiration());//存储Token
        // 4. 更新最后登录时间
        user.setLastLoginTime(new Date());
        this.updateById(user);
        // 6.构建返回结果，同时返回Token和信息脱敏的dto类
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("token", token);   // 返回Token
        resultMap.put("userInfo", userDTO); // 返回dto类（信息已脱敏）
        // 7.登录成功，用响应体类Result的success方法返回结果
        return Result.success(resultMap);
    }

    //    注册方法
    @Override
    public Result<UserDTO> register(RegisterRequest registerRequest) {
        // 1. 检查用户名是否已存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, registerRequest.getUsername());
        if (this.count(queryWrapper) > 0) {
            return Result.failed(ResponseCode.VALIDATE_FAILED.getCode(), "用户名已存在");
        }

        // 2. 检查邮箱是否已存在
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail, registerRequest.getEmail());
        if (this.count(queryWrapper) > 0) {
            return Result.failed(ResponseCode.VALIDATE_FAILED.getCode(), "邮箱已被注册");
        }

        // 3. 检查手机号是否已存在
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getPhone, registerRequest.getPhone());
        if (this.count(queryWrapper) > 0) {
            return Result.failed(ResponseCode.VALIDATE_FAILED.getCode(), "手机号已被注册");
        }

        // 4. 创建User实体对象，因为registerRequest转user不常用，使用最基本的setter方法
        User user = new User();
        user.setUsername(registerRequest.getUsername());

        // 5. 使用与BCrypt加密算法加密密码
        user.setPasswordHash(passwordEncoder.encode(registerRequest.getPassword()));
        user.setEmail(registerRequest.getEmail());
        user.setPhone(registerRequest.getPhone());
        user.setStatus(1); // 默认启用状态

        // 6. 保存到数据库（时间字段使用数据库自动填充）
        boolean saveResult = this.save(user);
        if (!saveResult) {
            return Result.failed(ResponseCode.FAILED.getCode(), "注册失败，请稍后重试");
        }

        // 7. 转换为DTO返回（排除敏感信息）
        UserDTO userDTO = UserDTO.fromEntity(user);
        return Result.success(userDTO);
    }

    //   退出登录的方法
    @Override
    public Result<String> logout(String token) {
        System.out.println("token is " + token);
        try {
            // 1. 从请求头中提取Token
//            String token = extractTokenFromRequest(request);

            if (token == null || token.trim().isEmpty()) {
                log.warn("退出登录时未找到有效的Token");
                return Result.failed("退出失败：未找到有效的Token");
            }

            // 2. 调用TokenManagerService进行退出处理
            tokenManagerService.logout(token);

            // 3. 返回成功响应
            return Result.success("退出登录成功");

        } catch (Exception e) {
            // 记录错误日志
            log.error("用户退出登录时发生错误", e);
            return Result.failed("退出登录失败，请稍后重试");
        }
    }

//管理员强制某用户下线

    @Override
//    @PreAuthorize("hasRole('ADMIN')") // 关键：使用Spring Security注解确保只有管理员可调用
//    未来加入权限控制再使用该注解
    public Result<String> forceLogoutUser(Long userId) {
        log.info("管理员发起强制下线操作，目标用户ID: {}", userId);
        try {
            // 1. 校验用户是否存在
            User targetUser = this.getById(userId);
            if (targetUser == null) {
                return Result.failed("用户不存在");
            }
            // 2. (可选) 防止管理员禁用自己，根据业务需求决定
//            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
//            Long currentAdminId = Long.parseLong(authentication.getName()); // 假设Principal中存储的是当前用户ID
//
//            if (userId.equals(currentAdminId)) {
//                log.warn("管理员尝试将自己强制下线，操作被禁止。管理员ID: {}", currentAdminId);
//                return Result.failed("不能强制下线您自己");
//            }

            // 3. 调用TokenManagerService执行核心拉黑逻辑
            tokenManagerService.forceLogoutUser(userId);
            log.info("用户所有Token已被强制拉黑，用户ID: {}", userId);
            return Result.success("用户已被强制下线");
        } catch (Exception e) {
            // 记录详细的错误日志，便于排查
            log.error("强制下线用户时发生系统错误，用户ID: " + userId, e);
            return Result.failed("系统错误，强制下线失败");
        }
    }

    /**
     * 从HttpServletRequest中提取Token的辅助方法
     */
    private String extractTokenFromRequest(HttpServletRequest request) {
        // 从Authorization头中提取Bearer Token
        String authHeader = request.getHeader("Authorization");
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            return authHeader.substring(7);
        }

        // 如果Authorization头不存在，尝试从其他位置获取（如参数）
        String tokenParam = request.getParameter("token");
        if (tokenParam != null && !tokenParam.trim().isEmpty()) {
            return tokenParam;
        }

        return null;
    }

    //    根据userId获取权限信息列表
    @Override
    public List<String> getUserRoles(Long userId) {
        return userMapper.selectRoleNamesByUserId(userId);
    }

    @Override
    public Result<PageResult<UserAddress>> getUserAddresses(UserAddressPageRequst request) {
        if (request.getUserId() == null)
            return Result.failed("用户ID不能为空");
        LambdaQueryWrapper<UserAddress> queryAddressWrapper = new LambdaQueryWrapper<>();
        queryAddressWrapper.eq(UserAddress::getUserId, request.getUserId());
        Page<UserAddress> page = new Page<>(request.getPageNum(), request.getPageSize());
        Page<UserAddress> ordersPage = userAddressMapper.selectPage(page, queryAddressWrapper);
        PageResult<UserAddress> pageResult = new PageResult<>(request.getPageNum(), request.getPageSize(), (int) ordersPage.getTotal(), ordersPage.getRecords());
        return Result.success(pageResult);
    }

    @Override
    public Result<UserAddress> getDefaultUserAddress(Long userId) {
        try {
            if (userId == null)
                return Result.failed("用户ID不能为空");
            LambdaQueryWrapper<UserAddress> queryAddressWrapper = new LambdaQueryWrapper<>();
            queryAddressWrapper.eq(UserAddress::getUserId, userId);
            queryAddressWrapper.eq(UserAddress::getIsDefault, 1);
            UserAddress userAddress = userAddressMapper.selectOne(queryAddressWrapper);
            if (userAddress == null)
                return Result.failed("没有找到默认地址");
            return Result.success(userAddress);
        } catch (Exception e) {
            return Result.failed("获取用户默认地址失败");
        }
    }
}

